module JumbleBoolean (Board, search) where

import Data.List (find)
import Data.Maybe (fromMaybe)

-- ----------------------------------------------------------------------------
--                                  T Y P E S
-- ----------------------------------------------------------------------------

type Pos    = (Int,Int) 
type Square = (Pos,Char)
type Board  = (Int,[Square])

-- ----------------------------------------------------------------------------
--                              A C C E S S O R S 
-- ----------------------------------------------------------------------------

boardWidth :: Board -> Int
boardWidth brd = fst brd

boardSquares :: Board -> [Square]
boardSquares brd = snd brd

squarePos :: Square -> Pos
squarePos sqr = fst sqr

squareChar :: Square -> Char
squareChar sqr = snd sqr

-- ----------------------------------------------------------------------------
--                        H E L P E R  F U N C T I O N S 
-- ----------------------------------------------------------------------------

getSquareFromPos :: Board -> Pos -> Maybe Square
getSquareFromPos brd pos = find (\p -> squarePos p == pos) (boardSquares brd)

neighbors :: Board -> Pos -> [Square]
neighbors brd (x,y) = map (fromMaybe ((-1,-1), ' '))
                           (filter (\n -> n /= Nothing) 
                                  [getSquareFromPos brd (x-1,y),
                                   getSquareFromPos brd (x+1,y),
                                   getSquareFromPos brd (x,y-1),
                                   getSquareFromPos brd (x,y+1),
                                   getSquareFromPos brd (x-1,y-1), 
                                   getSquareFromPos brd (x-1,y+1),
                                   getSquareFromPos brd (x+1,y-1),
                                   getSquareFromPos brd (x+1,y+1)])

searchFromSquare :: Board -> String -> Square -> Bool
searchFromSquare brd str sqr
    | null str                     = True
    | (head str) == squareChar sqr = or (map (searchFromSquare brd (tail str)) 
                                             (neighbors brd (squarePos sqr)))
    | otherwise                    = False

-- ----------------------------------------------------------------------------
--                      E X P O R T E D  F U N C T I O N S 
-- ----------------------------------------------------------------------------

search :: Board -> String -> Bool
search brd str = or (map (searchFromSquare brd str) (boardSquares brd)) 

